home *** CD-ROM | disk | FTP | other *** search
- /* IconMosaicView.m -- copyright 1993 by Christopher Lane */
-
- #import <c.h>
- #import <sys/dir.h>
- #import <mach-o/loader.h>
- #import <appkit/appkit.h>
-
- #import "Thinker.h"
- #import "DefaultsTable.h"
- #import "IconMosaicView.h"
-
- #define MODULE "IconMosaic"
- #define DEFAULTSFILE "Defaults.strings"
-
- #define IMAGEPATHS getDefault("IconMosaicImagePaths")
- #define SEGMENTLIST getDefault("IconMosaicSegmentList")
- #define IMAGESUFFIXLIST getDefault("IconMosaicImageSuffixList")
- #define APPSUFFIXLIST getDefault("IconMosaicApplicationSuffixList")
- #define IGNORESECTIONLIST getDefault("IconMosaicIgnoreSectionList")
-
- #define MAXIMUMSIZE getSizeDefault("IconMosaicMaximumSize")
- #define MAXIMUMBYTES getIntDefault("IconMosaicMaximumBytes")
-
- #define DENSITYDEFAULTNAME "IconMosaicDensity"
- #define DENSITY getFloatDefault(DENSITYDEFAULTNAME)
-
- #define PATHSEPARATOR "/"
- #define PATHSEPARATORCHAR (PATHSEPARATOR)[0]
- #define TOKENSEPARATOR ":"
- #define TOKENSEPARATORCHAR (TOKENSEPARATOR)[0]
- #define EXTENSIONSEPARATOR "."
- #define EXTENSIONSEPARATORCHAR (EXTENSIONSEPARATOR)[0]
-
- @implementation IconMosaicView
-
- static any_t search(id self)
- {
- char *path, *paths = NXCopyStringBuffer(IMAGEPATHS);
-
- for(path = strtok(paths, TOKENSEPARATOR); path != NULL; path = strtok(NULL, TOKENSEPARATOR))
- [self loadImagesFromDirectory:path];
-
- NX_FREE(paths);
-
- return self;
- }
-
- - initFrame:(NXRect *) frameRect
- {
- char buffer[MAXPATHLEN];
-
- [super initFrame:frameRect];
-
- [self allocateGState];
-
- images = [[List alloc] init];
-
- inspector = field = nil;
-
- thread = NO_CTHREAD;
-
- lock = mutex_alloc();
- condition = condition_alloc();
-
- (void) sprintf(buffer,"%s/%s", [[NXApp delegate] moduleDirectory:MODULE], DEFAULTSFILE);
- [(defaults = [[DefaultsTable alloc] initFromFile:buffer]) registerDefaults:[NXApp appName]];
-
- maximumSize = MAXIMUMSIZE;
-
- maximumBytes = MAXIMUMBYTES;
-
- srandom(time(NULL));
-
- return self;
- }
-
- - drawSelf:(const NXRect *) rects :(int) rectCount
- {
- if (rects == NULL || rectCount == 0) return self;
-
- PSsetgray(NX_BLACK);
-
- NXRectFill(rects);
-
- return self;
- }
-
- - didLockFocus
- {
- if(thread == NO_CTHREAD) cthread_detach(thread = cthread_fork((cthread_fn_t) search, (any_t) self));
-
- return self;
- }
-
- - free
- {
- mutex_lock(lock); {
- [[images freeObjects] free];
- (void) cthread_abort(thread);
- } mutex_unlock(lock);
-
- return [super free];
- }
-
- - oneStep
- {
- id image;
- NXSize size;
- unsigned int count;
- NXPoint point = { 0, 1 };
-
- condition_signal(condition);
-
- [self scrollRect:&bounds by:&point];
-
- if(((random() % 100) / 100.0) > [density floatValue]) return self;
-
- mutex_lock(lock); {
- count = [images count];
- } mutex_unlock(lock);
-
- if(count < 1) return self;
-
- mutex_lock(lock); {
- [(image = [images objectAt:(random() % count)]) getSize:&size];
- } mutex_unlock(lock);
-
- point.x = random() % (int) (bounds.size.width - size.width);
-
- [image composite:NX_SOVER toPoint:&point];
-
- if(field != nil && [field intValue] < count) [field setIntValue:count];
-
- return self;
- }
-
- - inspector:sender
- {
- char buffer[MAXPATHLEN];
-
- if (inspector == nil) {
- (void) sprintf(buffer,"%s/%s.nib", [sender moduleDirectory:MODULE], MODULE);
- [NXApp loadNibFile:buffer owner:self withNames:NO];
- }
-
- return inspector;
- }
-
- - inspectorInstalled
- {
- mutex_lock(lock); {
- [field setIntValue:[images count]];
- } mutex_unlock(lock);
-
- return self;
- }
-
- - (BOOL) useBufferedWindow { return YES; }
-
- - (const char *) windowTitle { return MODULE; }
-
- - setDefault:sender
- {
- [sender setTag:YES];
-
- if([density tag]) (void) writeDefault(DENSITYDEFAULTNAME, [density stringValue]);
-
- return self;
- }
-
- - setDensity:anObject
- {
- [(density = anObject) setFloatValue:DENSITY];
-
- return self;
- }
-
- - (BOOL) loadFromStream:(NXStream *) stream
- {
- NXSize size;
- BOOL result = NO;
- NXImage *image = [[NXImage alloc] init];
-
- if([image loadFromStream:stream]) {
- [image getSize:&size];
- if(size.width <= maximumSize.width && size.height <= maximumSize.height) {
- mutex_lock(lock); {
- [images addObject:image];
- condition_wait(condition, lock);
- } mutex_unlock(lock);
- result = YES;
- }
- else [image free];
- }
- else [image free];
-
- return result;
- }
-
- - (BOOL) member:(const char *) item ofSet:(const char *) set
- {
- BOOL result = NO;
- char *r, *s, *buffer = NXCopyStringBuffer(set);
- int index, length, itemLength = strlen(item);
-
- r = buffer;
-
- while((s = r) != NULL) {
- if((r = index(s, TOKENSEPARATORCHAR)) != NULL) *r++ = '\0';
-
- if((length = strlen(s)) > itemLength) continue;
- else index = itemLength - length;
-
- if(result = (strncmp(s, item + index, length) == 0)) break;
- }
-
- NX_FREE(buffer);
-
- return result;
- }
-
- - loadImagesFromDirectory:(const char *) directory
- {
- struct stat fs;
- NXStream *stream;
- struct direct *dp;
- char buffer[MAXPATHLEN];
- DIR *dirp = opendir(directory);
-
- if(dirp == NULL) return nil;
-
- for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
- (void) strcat(strcat(strcpy(buffer, directory), PATHSEPARATOR), dp->d_name);
- if(stat(buffer, &fs) == CERROR) continue;
- else if(fs.st_mode & S_IFDIR && (dp->d_name)[0] != EXTENSIONSEPARATORCHAR) [self loadImagesFromDirectory:buffer];
- else if(fs.st_size <= maximumBytes && [self member:dp->d_name ofSet:IMAGESUFFIXLIST]) {
- if((stream = NXMapFile(buffer, NX_READONLY)) != NULL) {
- if([self loadFromStream:stream]) {
- #ifdef DEBUG
- (void) fprintf(stderr, "%s\n", buffer);
- }
- else {
- (void) fprintf(stderr, "%s -- failed\n", buffer);
- #endif
- }
- NXCloseMemory(stream, NX_FREEBUFFER);
- }
- }
- else if(fs.st_mode & S_IEXEC && fs.st_mode & S_IFREG) [self loadImagesFromSegment:buffer];
- }
-
- (void) closedir(dirp);
-
- return self;
- }
-
- - loadImagesFromSegment:(const char *) filename
- {
- long offset;
- char *buffer;
- unsigned int i;
- NXStream *stream, *memory;
- unsigned long ncmds, nsects;
-
- struct mach_header m_header;
- struct load_command l_command;
- struct segment_command s_command;
- struct section s_section;
-
- if ((stream = NXMapFile(filename, NX_READONLY)) == NULL) return nil;
- if (NXRead(stream, &m_header, sizeof(m_header)) == sizeof(m_header) && m_header.magic == MH_MAGIC) {
-
- for (ncmds = m_header.ncmds; ncmds > 0; ncmds--) {
- offset = NXTell(stream);
- if (NXRead(stream, &l_command, sizeof(l_command)) != sizeof(l_command)) break;
- if (l_command.cmd == LC_SEGMENT) {
- NXSeek(stream, offset, NX_FROMSTART);
- if (NXRead(stream, &s_command, sizeof(s_command)) != sizeof(s_command)) break;
- if([self member:s_command.segname ofSet:SEGMENTLIST]) {
- for (nsects = 0; nsects < s_command.nsects; nsects++) {
- if (NXRead(stream, &s_section, sizeof(s_section)) != sizeof(s_section)) continue;
- else if(s_section.size > maximumBytes || [self member:s_section.sectname ofSet:IGNORESECTIONLIST]) continue;
-
- offset = NXTell(stream);
- NXSeek(stream, s_section.offset, NX_FROMSTART);
-
- (void) vm_allocate(task_self(), (vm_address_t *) &buffer, (vm_size_t) s_section.size, TRUE);
- for (i = 0; i < s_section.size; i++) buffer[i] = NXGetc(stream);
-
- if((memory = NXOpenMemory(buffer, s_section.size, NX_READONLY)) != NULL) {
- if([self loadFromStream:memory]) {
- #ifdef DEBUG
- (void) fprintf(stderr, "%s:%s:%s\n", filename, s_section.segname, s_section.sectname);
- }
- else {
- (void) fprintf(stderr, "%s:%s:%s -- failed\n", filename, s_section.segname, s_section.sectname);
- #endif
- }
-
- NXCloseMemory(memory, NX_FREEBUFFER);
- }
- NXSeek(stream, offset, NX_FROMSTART);
- }
- }
- else NXSeek(stream, s_command.cmdsize - sizeof(s_command), NX_FROMCURRENT);
- }
- else NXSeek(stream, l_command.cmdsize - sizeof(l_command), NX_FROMCURRENT);
- }
- }
-
- NXCloseMemory(stream, NX_FREEBUFFER);
-
- return self;
- }
-
- @end
-